package org.raymond.iworks.study.orders.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.raymond.iworks.apis.common.ErrorCode;
import org.raymond.iworks.apis.exception.BaseException;
import org.raymond.iworks.study.orders.common.GlobalCache;
import org.raymond.iworks.study.orders.entity.TInventoriesSeckillBook;
import org.raymond.iworks.study.orders.entity.TInventoriesSegments;
import org.raymond.iworks.study.orders.repository.TInventorySeckillBookRepository;
import org.raymond.iworks.study.orders.repository.TInventorySegmentsRepository;
import org.raymond.iworks.study.orders.service.IInventoryService;
import org.slf4j.helpers.BasicMarkerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
@Service
public class InventoryServiceImpl implements IInventoryService {
    @Autowired
    private TInventorySegmentsRepository tInventorySegmentsRepository;
    @Autowired
    private TInventorySeckillBookRepository tInventorySeckillBookRepository;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void lockInv(Long productId, Integer num) {
        GlobalCache globalCache = GlobalCache.instance();
        Map<Long, List<String>> segmentProductLockMap = globalCache.getSegmentProductLockMap();
        List<String> segmentLockList = segmentProductLockMap.get(productId);

        int lockSize = segmentLockList.size();

        Map<Long, Integer> rotateCountMap = globalCache.getRotateCountMap();
        // 期待不同的线程写不同的片段
        // 轮转计数递增到下一个,返回旧值
        Integer rotateCount = rotateCountMap.merge(productId, 1, Integer::sum);

        int segmentIdx = rotateCount % lockSize;
        String segmentlock = segmentLockList.get(segmentIdx);
        // 更新分段库存
        // 1,检查当前分段可用库存是否足够
        // 2,扣减可用库存并新增锁单库存
        // 3,为简化处理,当前分段可用库存不足时,即认为商品已售罄
        int effect = tInventorySegmentsRepository.updateInventoriesSegment(productId, segmentlock, num);
        // log.info("update effect: {}", effect);
        if (effect<=0) {
            // 简化处理
            throw new BaseException(ErrorCode.NOT_FOUND, "商品已售罄");
        }
    }

    @Override
    public void invReg(Long userId, Long productId) {
        TInventoriesSeckillBook book = TInventoriesSeckillBook.builder()
                .productId(productId)
                .userId(userId)
                .build();
        GlobalCache.instance().register(book);
    }
}
